from filestructs import StructReader, ListFile


class CodePoint(object):
    subclasses = {}
    REPR_ATTRS = []
    
    @classmethod
    def from_file(cls, listfile):
        return dict((i, CodePoint.create(data)) 
            for i, data in enumerate(listfile))
    
    @classmethod
    def from_filename(cls, filename):
        return cls.from_file(ListFile.open(filename))
    
    @classmethod
    def create(cls, data):
        kind = ord(data[0])
        return cls.subclasses[kind](data[1:])

    def __repr__(self):
        attrs = [repr(getattr(self, name)) for name in self.REPR_ATTRS]
        return "%s(%s)" % (self.__class__.__name__, ", ".join(attrs))


def register_codepoint(cls):
    CodePoint.subclasses[cls.TYPE] = cls

class FunctionCP(CodePoint):
    TYPE = 1
    REPR_ATTRS = ["filename", "name", "lineno"]

    def __init__(self, data):
        sr = StructReader(data)
        self.filename = sr.read_pstr()
        self.name = sr.read_pstr()
        self.lineno = sr.read_ui32()
        self.argcount = sr.read_ui16()
        self.flags = sr.read_ui8()
        self.varnames = []
        varnames_count = sr.read_ui16()
        for i in range(varnames_count):
            self.varnames.append(sr.read_pstr())
    
register_codepoint(FunctionCP)

class BuiltinCP(CodePoint):
    TYPE = 2
    REPR_ATTRS = ["module", "name"]

    def __init__(self, data):
        sr = StructReader(data)
        self.module = sr.read_pstr()
        self.name = sr.read_pstr()

register_codepoint(BuiltinCP)

class LogCP(CodePoint):
    TYPE = 3
    REPR_ATTRS = ["str"]

    def __init__(self, data):
        sr = StructReader(data)
        self.str = sr.read_pstr()

register_codepoint(LogCP)

class RootCP(CodePoint):
    TYPE = 4

    def __init__(self, data):
        pass

register_codepoint(RootCP)



if __name__ == "__main__":
    codepoints = CodePoint.from_filename("../../build/lib.linux-i686-2.5/foo-cp")
    print codepoints


